package com.tp7567.service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.drools.KnowledgeBase;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatelessKnowledgeSession;
import com.tp7567.domain.AutismLevel;
import com.tp7567.domain.Patient;
import com.tp7567.domain.Patient.SL;
import com.tp7567.domain.Patient.SC;
import com.tp7567.domain.Patient.SG;
import com.tp7567.domain.Patient.SF;
import com.tp7567.domain.Patient.SK;
import com.tp7567.domain.Patient.SJ;
import com.tp7567.domain.Patient.SD;
import com.tp7567.domain.Patient.PG;
import com.tp7567.domain.Patient.SM;
import com.tp7567.domain.Patient.SA;
import com.tp7567.domain.Patient.SN;
import com.tp7567.domain.Patient.SO;
import com.tp7567.domain.Patient.SB;
import com.tp7567.domain.Patient.SI;
import com.tp7567.domain.Patient.SH;
import com.tp7567.domain.Patient.SE;
import com.tp7567.domain.Patient.SP;
import com.tp7567.domain.Sintoma;

/**
 * 
 * @author Maxi Rosson
 */
@SuppressWarnings("serial")
public class TgdDiagnosticService implements Serializable {
	
	private final static TgdDiagnosticService INSTANCE = new TgdDiagnosticService();
	
	public static TgdDiagnosticService get() {
		return INSTANCE;
	}
	
	private Patient patient;
	private List<Question<? extends Sintoma>> questions;
	private Question<? extends Sintoma> currentQuestion;
	private int currentQuestionIndex;
	
	private TgdDiagnosticService() {
		createPatient();
		diagnose();
	}
	
	public void createPatient() {
		patient = new Patient();
		currentQuestionIndex = 0;
		questions = new ArrayList<Question<? extends Sintoma>>();
		questions.add(new Question<PG>("1- Genero del paciente", "", PG.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setPg((PG)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getPg();
			}
		});
		questions.add(new Question<SA>(
				"2- ¿Posee una alteración de las habilidades comunicativas?",
				"Abarca tres grandes aspectos: la capacidad comprensiva, expresiva y gestual.",
				SA.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSa((SA)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSa();
			}
		});
		questions.add(new Question<SB>(
				"3- ¿Presenta alguno de los siguientes problemas con respecto al desarrollo del lenguaje oral?",
				"Los sujetos pueden o no adquirir el lenguaje. Aquellos que lo adquieren pueden además presentar problemas funcionales(componente pragmático) y problemas formales (los aspectos fonológicos y sintácticos)",
				SB.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSb((SB)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSb();
			}
		});
		questions.add(new Question<SC>(
				"4- ¿Presenta comportamientos, intereses y actividades estereotipadas?",
				"Comportamientos que un niño repite con frecuencia como sacudir las manos, mover la cabeza, o balancearse. También puede adoptar posturas extravagantes y remplazar el pronombre “yo” por el “tu”",
				SC.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSc((SC)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSc();
			}
		});
		questions.add(new Question<SD>(
				"5- ¿Presenta dificultades en el desarrollo de vínculos?",
				"Alteraciones en la conducta social. Evitan la interacción social y si lo hacen es de forma anómala, estereotipada, carente de estimulación o buscando autoestimulación. Las relaciones carecen de componente afectivo.",
				SD.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSd((SD)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSd();
			}
		});
		questions.add(new Question<SE>("6- ¿Presenta retraso cognitivo?",
				"Coeficiente Intelectual del paciente.", SE.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSe((SE)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSe();
			}
		});
		questions.add(new Question<SF>(
				"7- ¿Presenta adhesión a conductas ritualizadas?",
				"Los chicos tienen la necesidad de mantener una invariabilidad en el entorno y se resisten a los cambios. El juego es ritualizado y carente de imaginación.",
				SF.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSf((SF)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSf();
			}
		});
		questions.add(new Question<SG>("8- ¿Presenta conductas de autolisis?",
				"Se refiere a los actos de autoagreción como morderse, golpearse la cabeza o arrancarse el pelo.",
				SG.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSg((SG)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSg();
			}
		});
		questions.add(new Question<SH>(
				"9- ¿Presenta perdidas de habilidades previamente adquiridas?",
				"Algunos pacientes tienen un desarrollo normal durante un periodo de 3 a 4 años donde luego entran en un deterioro progresivo donde pueden perder habilidades previamente adquiridas.",
				SH.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSh((SH)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSh();
			}
		});
		questions.add(new Question<SI>("10- ¿A que edad se manifestaron los primeros sintomas?",
				"Los síntomas pueden manifestarse antes de los 3 años, entre los 3 a 5 años o a una edad mas tardía.",
				SI.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSi((SI)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSi();
			}
		});
		questions.add(new Question<SJ>(
				"11- ¿Presenta algun tipo de dificultad en el desarrollo psicomotor?",
				"Esta relacionado con las habilidades motoras. Puede ir desde una mala coordinación de la marcha o de los movimientos del tronco hasta presentar la incapacidad de caminar.",
				SJ.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSj((SJ)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSj();
			}
		});
		questions.add(new Question<SK>("12- ¿Presenta problemas de control intestinal o vesical?",
				"Algunos pacientes pueden llegar a tener problemas con el control intestinal y vesical.",
				SK.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSk((SK)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSk();
			}
		});
		questions.add(new Question<SL>(
				"13- ¿Presenta ausencia de la tendencia espontánea a compartir disfrutes?",
				"Esta relacionado con el hecho de no sentir la necesidad o el querer expresarse. No se observan acciones como la de traer o señalar objetos de interes.",
				SL.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSl((SL)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSl();
			}
		});
		questions.add(new Question<SM>(
				"14- ¿Presenta alguna alteración del uso de los gestos reguladores de la interacción social?",
				"Alteraciones del uso de múltiples comportamientos no verbales, como son el contacto ocular, expresión facial, posturas corporales y gestos.",
				SM.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSm((SM)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSm();
			}
		});
		questions.add(new Question<SN>(
				"15- ¿Presenta habilidades inusuales?",
				"Los que tienen un CI más alto pueden presentar habilidades inusuales en alguna área: dibujo, arismética, cálculo o música y en ocaciones habilidad para la lectura y memorización pero sin comprensión de texto.",
				SN.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSn((SN)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSn();
			}
		});
		questions.add(new Question<SO>(
				"16- ¿Presenta una ausencia del juego realista espontáneo?",
				"Falta de juego usual, espontáneo o juego imitativo social y juego imaginativo.",
				SO.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSo((SO)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSo();
			}
		});
		questions.add(new Question<SP>(
				"17- ¿Presenta tolerancia al dolor?",
				"Suelen carecer o tener una tolerancia alta al dolor, se golpean muy fuerte y no expresan dolor aparente. Todo ello puede combinarse por una falta total de sensación de peligro en situaciones en las que objetivamente lo hay.",
				SP.values()) {
			
			@Override
			public void executeAnswer(Patient patient, Sintoma answer) {
				patient.setSp((SP)answer);
			}
			
			@Override
			public Sintoma getSelectedAnswer(Patient patient) {
				return patient.getSp();
			}
		});
		currentQuestion = questions.get(currentQuestionIndex);
	}
	
	public Question<? extends Sintoma> getCurrentQuestion() {
		return currentQuestion;
	}
	
	public void prevQuestion() {
		if (currentQuestionIndex > 0) {
			currentQuestionIndex--;
			currentQuestion = questions.get(currentQuestionIndex);
		}
	}
	
	public void nextQuestion() {
		if (currentQuestionIndex + 1 < questions.size()) {
			currentQuestionIndex++;
			currentQuestion = questions.get(currentQuestionIndex);
		}
	}
	
	public Boolean hasNextQuestion() {
		return currentQuestionIndex + 1 != questions.size();
	}
	
	public Boolean hasPrevQuestion() {
		return currentQuestionIndex > 0;
	}
	
	public AutismLevel diagnose() {
		
		KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
		kbuilder.add(ResourceFactory.newClassPathResource("rules/rule1.drl"), ResourceType.DRL);
		KnowledgeBase kbase = kbuilder.newKnowledgeBase();
		kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
		
		// StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
		StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
		
		ksession.execute(patient);
		// ksession.insert(patient);
		// ksession.fireAllRules();
		
		System.out.println(patient);
		
		return patient.getAutismLevel();
	}
	
	public List<AutismLevel> inverseDiagnose() {
		
		patient.resetAvailables();
		
		KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
		kbuilder.add(ResourceFactory.newClassPathResource("rules/rule2.drl"), ResourceType.DRL);
		KnowledgeBase kbase = kbuilder.newKnowledgeBase();
		kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
		
		// StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
		StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
		
		ksession.execute(patient);
		// ksession.insert(patient);
		// ksession.fireAllRules();
		
		System.out.println(patient);
		
		return patient.getAvailableAutismLevels();
	}
	
	/**
	 * @return the patient
	 */
	public Patient getPatient() {
		return patient;
	}
}
